// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-07-22

package src

var (
	staticPaging = &Paging{}
)

// Paging
// is a component used to store paginator.
type Paging struct {
	// Total
	// is total amount of items.
	Total int64 `json:"total" xml:"total"`

	// Size
	// show items amount on each page.
	Size int `json:"size" xml:"size"`

	// First
	// shows the start page number of paginator.
	First int `json:"first" xml:"first"`

	// Prev
	// shows previous page number of paginator.
	Prev int `json:"prev" xml:"prev"`

	// Curr
	// shows the current page number of paginator.
	Curr int `json:"curr" xml:"curr"`

	// Next
	// shows the next page number of paginator.
	Next int `json:"next" xml:"next"`

	// Last
	// shows the last page number of paginator.
	Last int `json:"last" xml:"last"`
}

// NewPaging
// create a new paginator component.
func NewPaging(total int64, page int, size int) *Paging {
	// Amount on each page can not less than 1.
	if size < 1 || total == 0 {
		return staticPaging
	}

	// Execute
	// paginator fields.
	o := &Paging{Total: total, Size: size, First: 1, Curr: page}

	// Last page number calculation.
	o.Last = int(total / int64(size))
	if m := total % int64(size); m > 0 {
		o.Last += 1
	}

	// Current page number can not less than first.
	if o.Curr < o.First {
		o.Curr = o.First
	}

	// Current page number can not greater than last.
	if o.Curr > o.Last {
		o.Curr = o.Last
	}

	// Previous page number calculation.
	if o.Prev = o.Curr - 1; o.Prev < o.First {
		o.Prev = o.First
	}

	// Next page number calculation.
	if o.Next = o.Curr + 1; o.Next > o.Last {
		o.Next = o.Last
	}
	return o
}
